import requests
from common import yaml_util, Log, config_util
from urllib.parse import urljoin
import traceback

# 封装的 request 类，用于接收请求参数发送请求，返回 response
class RequestsUtil:
    def __init__(self):
        self.session = requests.Session()

    def all_send_request(self, method, url, headers=None, data=None):
        """
        统一发送 HTTP 请求的方法。
        """
        # 统一处理 GET 请求的参数
        request_kwargs = {
            'headers': headers,
            'params' if method.lower() == 'get' else 'json': data
        }
        return self.session.request(method, url, **request_kwargs)

requests_util_instance = RequestsUtil()

# 封装类，进行调用 request 类进行请求，获得 response 后进行断言，打印日志操作
class TestUtil:
    logger = Log.logger

    def __init__(self):
        self.util_instance = requests_util_instance
        self.domain_name = config_util.Config('test2')

    def send_request_and_assert(self, case, yaml_file):
        try:
            read_yaml = yaml_util.Yaml_Util().read_testcase_yaml(yaml_file)
            res = self.util_instance.all_send_request(
                method=case['method'],
                url=urljoin(self.domain_name.base_url, case['url']),
                headers=read_yaml['header'],
                data=case['data']
            )
            res.raise_for_status()  # 检查响应状态码，若不是 200-299 则抛出异常

            if 'expected' in case:
                self._assert_response(res, case)
            return res
        except Exception as e:
            self._log_error(case, e, res if 'res' in locals() else None)
            raise

    def _assert_response(self, res, case):
        """
        对响应进行断言检查。
        """
        # 断言状态码
        assert res.status_code == case['expected']['status_code'], \
            f"Expected status code {case['expected']['status_code']}, but got {res.status_code}"

        # 断言响应 JSON
        if 'json' in case['expected']:
            assert res.json()['code'] == case['expected']['json']['code'], \
                f"Expected code {case['expected']['json']['code']}, but got {res.json().get('code')}"
            self.logger.info("------------------------")
            self.logger.info(f"Test case {case['name']} passed")
            self.logger.info("------------------------")

    def _log_error(self, case, e, res=None):
        """
        记录错误日志。
        """
        self.logger.error(f"Test case {case['name']} failed: {e}")
        if res:
            try:
                self.logger.error(f"Actual: {res.json()}")
            except ValueError:
                self.logger.error(f"Actual: {res.text}")
        self.logger.error("".join(traceback.format_exception(None, e, e.__traceback__)))

# TestUtil 创建的类实例，提供给其他方法调用
Reqs = TestUtil()

if __name__ == '__main__':
    pass
